home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / src / lex.l < prev    next >
Text File  |  1997-05-26  |  45KB  |  2,007 lines

  1. /*
  2.  
  3. Copyright (C) 1996 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. */
  22.  
  23. /* Modified by Klaus Gebhardt, 1996 */
  24.  
  25. %s TEXT_FCN
  26. %s MATRIX
  27.  
  28. %{
  29. #ifdef HAVE_CONFIG_H
  30. #include <config.h>
  31. #endif
  32.  
  33. #include <cctype>
  34. #include <cstring>
  35.  
  36. #include <string>
  37.  
  38. #include <strstream.h>
  39.  
  40. #include "SLStack.h"
  41.  
  42. // These would be alphabetical, but y.tab.h must be included before
  43. // oct-gperf.h and y.tab.h must be included after token.h and the tree
  44. // class declarations.  We can't include y.tab.h in oct-gperf.h
  45. // because it may not be protected to allow it to be included multiple
  46. // times.
  47.  
  48. #include "defun.h"
  49. #include "error.h"
  50. #include "input.h"
  51. #include "lex.h"
  52. #include "toplev.h"
  53. #include "parse.h"
  54. #include "symtab.h"
  55. #include "token.h"
  56. #include "pt-base.h"
  57. #include "pt-cmd.h"
  58. #include "ov.h"
  59. #include "pt-exp.h"
  60. #include "pt-mat.h"
  61. #include "pt-misc.h"
  62. #include "pt-plot.h"
  63. #include "utils.h"
  64. #include "variables.h"
  65. #include <y.tab.h>
  66. #include <oct-gperf.h>
  67.  
  68. #if ! (defined (FLEX_SCANNER) \
  69.        && defined (YY_FLEX_MAJOR_VERSION) && YY_FLEX_MAJOR_VERSION >= 2 \
  70.        && defined (YY_FLEX_MINOR_VERSION) && YY_FLEX_MINOR_VERSION >= 5)
  71. #error lex.l requires flex version 2.5.4 or later
  72. #endif
  73.  
  74. // Flags that need to be shared between the lexer and parser.
  75. lexical_feedback lexer_flags;
  76.  
  77. // Stack to hold tokens so that we can delete them when the parser is
  78. // reset and avoid growing forever just because we are stashing some
  79. // information.  This has to appear before lex.h is included, because
  80. // one of the macros defined there uses token_stack.
  81. //
  82. // XXX FIXME XXX -- this should really be static, but that causes
  83. // problems on some systems.
  84. SLStack <token*> token_stack;
  85.  
  86. // Did eat_whitespace() eat a space or tab, or a newline, or both?
  87.  
  88. typedef int yum_yum;
  89.  
  90. const yum_yum ATE_NOTHING = 0;
  91. const yum_yum ATE_SPACE_OR_TAB = 1;
  92. const yum_yum ATE_NEWLINE = 2;
  93.  
  94. // Is the closest nesting level a square brace or a paren?
  95.  
  96. class brace_paren_nesting_level : public SLStack <int>
  97. {
  98. public:
  99.  
  100.   brace_paren_nesting_level (void) : SLStack<int> () { }
  101.  
  102.   ~brace_paren_nesting_level (void) { }
  103.  
  104.   void brace (void) { push (BRACE); }
  105.   bool is_brace (void) { return ! empty () && top () == BRACE; }
  106.  
  107.   void paren (void) { push (PAREN); }
  108.   bool is_paren (void) { return ! empty () && top () == PAREN; }
  109.  
  110.   bool none (void) { return empty (); }
  111.  
  112.   void remove (void) { if (! empty ()) SLStack<int>::pop (); }
  113.  
  114. private:
  115.  
  116.   enum { BRACE = 1, PAREN = 2 };
  117.  
  118.   brace_paren_nesting_level (const brace_paren_nesting_level&);
  119.  
  120.   brace_paren_nesting_level& operator = (const brace_paren_nesting_level&);
  121. };
  122.  
  123. static brace_paren_nesting_level nesting_level;
  124.  
  125. // Should whitespace in a literal matrix list be automatically
  126. // converted to commas and semicolons?
  127. //
  128. //   user specifies   value of var
  129. //   --------------   ------------
  130. //   "ignore"              2
  131. //   "traditional"         1
  132. //   anything else         0
  133. //
  134. // Octave will never insert a comma in a literal matrix list if the
  135. // user specifies "ignore".  For example, the statement [1 2] will
  136. // result in an error instead of being treated the same as [1, 2], and
  137. // the statement
  138. //
  139. //   [ 1, 2,
  140. //     3, 4 ]
  141. //
  142. // will result in the vector [1 2 3 4] instead of a matrix.
  143. //
  144. // Traditional behavior makes Octave convert spaces to a comma between
  145. // identifiers and `('.  For example, the statement
  146. //
  147. //   [eye (2)]
  148. //
  149. // will be parsed as
  150. //
  151. //   [eye, (2)]
  152. //
  153. // and will result in an error since the `eye' function will be
  154. // called with no arguments.  To get around this, you would have to
  155. // omit the space between `eye' and the `('.
  156. //
  157. // The default value is 0, which results in behavior that is the same
  158. // as traditional, except that Octave does not convert spaces to a
  159. // comma between identifiers and `('.  For example, the statement
  160. //
  161. //   [eye (2)]
  162. //
  163. // will result in a call to `eye' with the argument `2'.
  164.  
  165. static int Vwhitespace_in_literal_matrix;
  166.  
  167.  
  168. // Forward declarations for functions defined at the bottom of this
  169. // file.
  170.  
  171. static void do_string_escapes (char *s);
  172. static void fixup_column_count (char *s);
  173. static void do_comma_insert_check (void);
  174. static int is_plot_keyword (const string& s);
  175. static int is_keyword (const string& s);
  176. static string plot_style_token (const string& s);
  177. static symbol_record *lookup_identifier (const string& s);
  178. static void grab_help_text (void);
  179. static int match_any (char c, char *s);
  180. static int next_token_is_bin_op (int spc_prev, char *yytext);
  181. static int next_token_is_postfix_unary_op (int spc_prev, char *yytext);
  182. static string strip_trailing_whitespace (char *s);
  183. static void handle_number (char *yytext);
  184. static int handle_string (char delim, int text_style = 0);
  185. static int handle_close_brace (int spc_gobbled);
  186. static int handle_identifier (const string& tok, int spc_gobbled);
  187. static int have_continuation (int trailing_comments_ok = 1);
  188. static int have_ellipsis_continuation (int trailing_comments_ok = 1);
  189. static yum_yum eat_whitespace (void);
  190. static yum_yum eat_continuation (void);
  191.  
  192. %}
  193.  
  194. D    [0-9]
  195. S    [ \t]
  196. NL    ((\n)|(\r)|(\r\n)|())
  197. SNL    ({S}|{NL})
  198. EL    (\.\.\.)
  199. BS    (\\)
  200. CONT    ({EL}|{BS})
  201. Im    [iIjJ]
  202. CCHAR    [#%]
  203. COMMENT    ({CCHAR}.*{NL})
  204. SNLCMT    ({SNL}|{COMMENT})
  205. NOTEQ    ((~=)|(!=)|(<>))
  206. POW    ((\*\*)|(\^))
  207. EPOW    (\.{POW})
  208. NOT    ((\~)|(\!))
  209. IDENT    ([_a-zA-Z][_a-zA-Z0-9]*)
  210. EXPON    ([DdEe][+-]?{D}+)
  211. NUMBER    (({D}+\.?{D}*{EXPON}?)|(\.{D}+{EXPON}?))
  212. %%
  213.  
  214. %{
  215. // Help and other text-style functions are a pain in the ass.  This
  216. // stuff needs to be simplified.  May require some changes in the
  217. // parser too.
  218. %}
  219.  
  220. <TEXT_FCN>{NL} {
  221.     BEGIN 0;
  222.     current_input_column = 1;
  223.     lexer_flags.quote_is_transpose = 0;
  224.     lexer_flags.cant_be_identifier = 0;
  225.     lexer_flags.convert_spaces_to_comma = 1;
  226.     return '\n';
  227.   }
  228.  
  229. <TEXT_FCN>[\;\,] {
  230.     if (lexer_flags.doing_set && strcmp (yytext, ",") == 0)
  231.       {
  232.     TOK_PUSH_AND_RETURN (yytext, TEXT);
  233.       }
  234.     else
  235.       {
  236.     BEGIN 0;
  237.     if (strcmp (yytext, ",") == 0)
  238.       TOK_RETURN (',');
  239.     else
  240.       TOK_RETURN (';');
  241.       }
  242.   }
  243.  
  244. <TEXT_FCN>[\"\'] {
  245.     current_input_column++;
  246.     return handle_string (yytext[0], 1);
  247.   }
  248.  
  249. <TEXT_FCN>[^ \t\r\n\;\,]*{S}* {
  250.     string tok = strip_trailing_whitespace (yytext);
  251.     TOK_PUSH_AND_RETURN (tok, TEXT);
  252.   }
  253.  
  254. %{
  255. // For this and the next two rules, we're looking at ']', and we
  256. // need to know if the next token is `=' or `=='.
  257. //
  258. // It would have been so much easier if the delimiters were simply
  259. // different for the expression on the left hand side of the equals
  260. // operator.
  261. //
  262. // It's also a pain in the ass to decide whether to insert a comma
  263. // after seeing a ']' character...
  264. %}
  265.  
  266. <MATRIX>{SNLCMT}*\]{S}* {
  267.     fixup_column_count (yytext);
  268.     int c = yytext[yyleng-1];
  269.     int cont_is_spc = eat_continuation ();
  270.     int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
  271.     return handle_close_brace (spc_gobbled);
  272.   }
  273.  
  274. %{
  275. // Commas are element separators in matrix constants.  If we don't
  276. // check for continuations here we can end up inserting too many
  277. // commas.
  278. %}
  279.  
  280. <MATRIX>{S}*\,{S}* {
  281.     current_input_column += yyleng;
  282.     int tmp = eat_continuation ();
  283.     lexer_flags.quote_is_transpose = 0;
  284.     lexer_flags.cant_be_identifier = 0;
  285.     lexer_flags.convert_spaces_to_comma = 1;
  286.     if (Vwhitespace_in_literal_matrix != 2
  287.     && (tmp & ATE_NEWLINE) == ATE_NEWLINE)
  288.       unput (';');
  289.     return (',');
  290.   }
  291.  
  292. %{
  293. // In some cases, spaces in matrix constants can turn into commas.
  294. // If commas are required, spaces are not important in matrix
  295. // constants so we just eat them.  If we don't check for continuations
  296. // here we can end up inserting too many commas.
  297. %}
  298.  
  299. <MATRIX>{S}+ {
  300.     current_input_column += yyleng;
  301.     if (Vwhitespace_in_literal_matrix != 2)
  302.       {
  303.     int tmp = eat_continuation ();
  304.     int bin_op = next_token_is_bin_op (1, yytext);
  305.     int postfix_un_op = next_token_is_postfix_unary_op (1, yytext);
  306.  
  307.     if (! (postfix_un_op || bin_op)
  308.         && nesting_level.is_brace ()
  309.         && lexer_flags.convert_spaces_to_comma)
  310.       {
  311.         lexer_flags.quote_is_transpose = 0;
  312.         lexer_flags.cant_be_identifier = 0;
  313.         lexer_flags.convert_spaces_to_comma = 1;
  314.         if ((tmp & ATE_NEWLINE) == ATE_NEWLINE)
  315.           unput (';');
  316.         return (',');
  317.       }
  318.       }
  319.   }
  320.  
  321. %{
  322. // Semicolons are handled as row seprators in matrix constants.  If we
  323. // don't eat whitespace here we can end up inserting too many
  324. // semicolons.
  325. %}
  326.  
  327. <MATRIX>{SNLCMT}*;{SNLCMT}* {
  328.     fixup_column_count (yytext);
  329.     eat_whitespace ();
  330.     lexer_flags.quote_is_transpose = 0;
  331.     lexer_flags.cant_be_identifier = 0;
  332.     lexer_flags.convert_spaces_to_comma = 1;
  333.     return ';';
  334.   }
  335.  
  336. %{
  337. // In some cases, new lines can also become row separators.  If we
  338. // don't eat whitespace here we can end up inserting too many
  339. // semicolons.
  340. %}
  341.  
  342. <MATRIX>{SNLCMT}*\n{SNLCMT}* {
  343.     fixup_column_count (yytext);
  344.     eat_whitespace ();
  345.     if (Vwhitespace_in_literal_matrix != 2)
  346.       {
  347.     lexer_flags.quote_is_transpose = 0;
  348.     lexer_flags.cant_be_identifier = 0;
  349.     lexer_flags.convert_spaces_to_comma = 1;
  350.  
  351.     if (nesting_level.none ())
  352.       return LEXICAL_ERROR;
  353.  
  354.     if (nesting_level.is_brace ())
  355.       return ';';
  356.       }
  357.   }
  358.  
  359. %{
  360. // Open and close brace are handled differently if we are in the range
  361. // part of a plot command.
  362. //
  363. %}
  364.  
  365. \[{S}* {
  366.     nesting_level.brace ();
  367.  
  368.     current_input_column += yyleng;
  369.     lexer_flags.quote_is_transpose = 0;
  370.     lexer_flags.cant_be_identifier = 0;
  371.     lexer_flags.convert_spaces_to_comma = 1;
  372.  
  373.     promptflag--;
  374.     eat_whitespace ();
  375.  
  376.     if (lexer_flags.plotting && ! lexer_flags.past_plot_range)
  377.       {
  378.     lexer_flags.in_plot_range = 1;
  379.     return OPEN_BRACE;
  380.       }
  381.     else
  382.       {
  383.     lexer_flags.braceflag++;
  384.     BEGIN MATRIX;
  385.     return '[';
  386.       }
  387.   }
  388.  
  389. \] {
  390.     nesting_level.remove ();
  391.  
  392.     if (lexer_flags.plotting && ! lexer_flags.past_plot_range)
  393.       {
  394.     lexer_flags.in_plot_range = 0;
  395.     TOK_RETURN (CLOSE_BRACE);
  396.       }
  397.     else
  398.       TOK_RETURN (']');
  399.   }
  400.  
  401. %{
  402. // Imaginary numbers.
  403. %}
  404.  
  405. {NUMBER}{Im} {
  406.     handle_number (yytext);
  407.     return IMAG_NUM;
  408.   }
  409.  
  410. %{
  411. // Real numbers.  Don't grab the `.' part of a dot operator as part of
  412. // the constant.
  413. %}
  414.  
  415. {D}+/\.[\*/\\^'] |
  416. {NUMBER} {
  417.     handle_number (yytext);
  418.     return NUM;
  419.   }
  420.  
  421. %{
  422. // Eat whitespace.  Whitespace inside matrix constants is handled by
  423. // the <MATRIX> start state code above.
  424. %}
  425.  
  426. {S}* {
  427.     current_input_column += yyleng;
  428.   }
  429.  
  430. %{
  431. // Continuation lines.  Allow comments after continuations.
  432. %}
  433.  
  434. {CONT}{S}*{NL} |
  435. {CONT}{S}*{COMMENT} {
  436.     promptflag--;
  437.     current_input_column = 1;
  438.   }
  439.  
  440. %{
  441. // An ellipsis not at the end of a line is not a continuation, but
  442. // does have another meaning.
  443. %}
  444.  
  445. {EL} {
  446.     return ELLIPSIS;
  447.   }
  448.  
  449. %{
  450. // End of file.
  451. %}
  452.  
  453. <<EOF>> {
  454.     TOK_RETURN (END_OF_INPUT);
  455.   }
  456.  
  457. %{
  458. // Identifiers.  Truncate the token at the first space or tab but
  459. // don't write directly on yytext.
  460. %}
  461.  
  462. {IDENT}{S}* {
  463.     string tok = strip_trailing_whitespace (yytext);
  464.     int c = yytext[yyleng-1];
  465.     int cont_is_spc = eat_continuation ();
  466.     int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
  467.     return handle_identifier (tok, spc_gobbled);
  468.   }
  469.  
  470. %{
  471. // A new line character.  New line characters inside matrix constants
  472. // are handled by the <MATRIX> start state code above.  If closest
  473. // nesting is inside parentheses, don't return a row separator.
  474. %}
  475.  
  476. {NL} {
  477.     current_input_column = 1;
  478.     lexer_flags.quote_is_transpose = 0;
  479.     lexer_flags.cant_be_identifier = 0;
  480.     lexer_flags.convert_spaces_to_comma = 1;
  481.  
  482.     if (nesting_level.none ())
  483.       return '\n';
  484.  
  485.     if (nesting_level.is_brace ())
  486.       return LEXICAL_ERROR;
  487.   }
  488.  
  489. %{
  490. // Single quote can either be the beginning of a string or a transpose
  491. // operator. 
  492. %}
  493.  
  494. "'" {
  495.     current_input_column++;
  496.     lexer_flags.convert_spaces_to_comma = 1;
  497.  
  498.     if (lexer_flags.quote_is_transpose)
  499.       {
  500.     do_comma_insert_check ();
  501.     return QUOTE;
  502.       }
  503.     else
  504.       return handle_string ('\'');
  505.   }
  506.  
  507. %{
  508. // Double quotes always begin strings.
  509. %}
  510.  
  511. \" {
  512.     current_input_column++;
  513.     return handle_string ('"');
  514. }
  515.  
  516. %{
  517. // The colon operator is handled differently if we are in the range
  518. // part of a plot command.
  519. %}
  520.  
  521. ":" {
  522.     if (lexer_flags.plotting
  523.     && (lexer_flags.in_plot_range || lexer_flags.in_plot_using))
  524.       BIN_OP_RETURN (COLON, 1);
  525.     else
  526.       BIN_OP_RETURN (':', 0);
  527.   }
  528.  
  529. %{
  530. // Gobble comments.  If closest nesting is inside parentheses, don't
  531. // return a new line.
  532. %} 
  533.  
  534. {CCHAR} {
  535.     if (help_buf.empty ()
  536.     && lexer_flags.beginning_of_function
  537.     && nesting_level.none ())
  538.       {
  539.     grab_help_text ();
  540.     lexer_flags.beginning_of_function = 0;
  541.       }
  542.     else
  543.       {
  544.     int c;
  545.     while ((c = yyinput ()) != EOF && c != '\n' && c != '\r' && c != '')
  546.       ; // Eat comment.
  547.       }
  548.  
  549.     current_input_column = 1;
  550.     lexer_flags.quote_is_transpose = 0;
  551.     lexer_flags.cant_be_identifier = 0;
  552.     lexer_flags.convert_spaces_to_comma = 1;
  553.  
  554.     if (nesting_level.none ())
  555.       return '\n';
  556.     else if (nesting_level.is_brace ())
  557.       return ';';
  558.   }
  559.  
  560. %{
  561. // Other operators.
  562. %}
  563.  
  564. ".+"        { BIN_OP_RETURN (EPLUS, 0); }
  565. ".-"        { BIN_OP_RETURN (EMINUS, 0); }
  566. ".*"        { BIN_OP_RETURN (EMUL, 0); }
  567. "./"        { BIN_OP_RETURN (EDIV, 0); }
  568. ".\\"        { BIN_OP_RETURN (ELEFTDIV, 0); }
  569. {EPOW}        { BIN_OP_RETURN (EPOW, 0); }
  570. ".'"        { do_comma_insert_check (); BIN_OP_RETURN (TRANSPOSE, 1); }
  571. "++"        { do_comma_insert_check (); BIN_OP_RETURN (PLUS_PLUS, 1); }
  572. "--"        { do_comma_insert_check (); BIN_OP_RETURN (MINUS_MINUS, 1); }
  573. "<="        { BIN_OP_RETURN (EXPR_LE, 0); }
  574. "=="        { BIN_OP_RETURN (EXPR_EQ, 0); }
  575. {NOTEQ}        { BIN_OP_RETURN (EXPR_NE, 0); }
  576. ">="        { BIN_OP_RETURN (EXPR_GE, 0); }
  577. "|"        { BIN_OP_RETURN (EXPR_OR, 0); }
  578. "&"        { BIN_OP_RETURN (EXPR_AND, 0); }
  579. "<"        { BIN_OP_RETURN (EXPR_LT, 0); }
  580. ">"        { BIN_OP_RETURN (EXPR_GT, 0); }
  581. "*"        { BIN_OP_RETURN ('*', 0); }
  582. "/"        { BIN_OP_RETURN ('/', 0); }
  583. "\\"        { BIN_OP_RETURN (LEFTDIV, 0); }
  584. ";"        { BIN_OP_RETURN (';', 1); }
  585. ","        { BIN_OP_RETURN (',', 1); }
  586. {POW}        { BIN_OP_RETURN (POW, 0); }
  587. "="        { BIN_OP_RETURN ('=', 1); }
  588. "||"        { BIN_OP_RETURN (EXPR_OR_OR, 0); }
  589. "&&"        { BIN_OP_RETURN (EXPR_AND_AND, 0); }
  590.  
  591. {NOT} {
  592.     if (lexer_flags.plotting && ! lexer_flags.in_plot_range)
  593.       lexer_flags.past_plot_range = 1;
  594.     BIN_OP_RETURN (EXPR_NOT, 0);
  595.   }
  596.  
  597. "+" { 
  598.     if (lexer_flags.plotting && ! lexer_flags.in_plot_range)
  599.       lexer_flags.past_plot_range = 1;
  600.     BIN_OP_RETURN ('+', 0);
  601.   }
  602.  
  603. "-" { 
  604.     if (lexer_flags.plotting && ! lexer_flags.in_plot_range)
  605.       lexer_flags.past_plot_range = 1;
  606.     BIN_OP_RETURN ('-', 0);
  607.   }
  608.  
  609. "(" {
  610.     if (lexer_flags.plotting && ! lexer_flags.in_plot_range)
  611.       lexer_flags.past_plot_range = 1;
  612.     nesting_level.paren ();
  613.     promptflag--;
  614.     TOK_RETURN ('(');
  615.   }
  616.  
  617. ")" {
  618.     nesting_level.remove ();
  619.  
  620.     current_input_column++;
  621.     lexer_flags.cant_be_identifier = 1;
  622.     lexer_flags.quote_is_transpose = 1;
  623.     lexer_flags.convert_spaces_to_comma = nesting_level.is_brace ();
  624.     do_comma_insert_check ();
  625.     return ')';
  626.   }
  627.  
  628. "." {
  629.     TOK_RETURN ('.');
  630.   }
  631.  
  632. %{
  633. // Unrecognized input is a lexical error.
  634. %}
  635.  
  636. . {
  637.     current_input_column++;
  638.  
  639.     error ("invalid character `%s' near line %d, column %d",
  640.        undo_string_escape (yytext[0]), input_line_number,
  641.        current_input_column);
  642.  
  643.     return LEXICAL_ERROR;
  644.   }
  645.  
  646. %%
  647.  
  648. // GAG.
  649. //
  650. // If we're reading a matrix and the next character is '[', make sure
  651. // that we insert a comma ahead of it.
  652.  
  653. void
  654. do_comma_insert_check (void)
  655. {
  656.   int spc_gobbled = eat_continuation ();
  657.   int c = yyinput ();
  658.   yyunput (c, yytext);
  659.   if (spc_gobbled)
  660.     yyunput (' ', yytext);
  661.   lexer_flags.do_comma_insert = (lexer_flags.braceflag && c == '[');
  662. }
  663.  
  664. // Fix things up for errors or interrupts.  The parser is never called
  665. // recursively, so it is always safe to reinitialize its state before
  666. // doing any parsing.
  667.  
  668. void
  669. reset_parser (void)
  670. {
  671.   // Start off on the right foot.
  672.   BEGIN 0;
  673.   error_state = 0;
  674.  
  675.   // We do want a prompt by default.
  676.   promptflag = 1;
  677.  
  678.   // Error may have occurred inside some parentheses or braces.
  679.   nesting_level.clear ();
  680.  
  681.   // Clear out the stack of token info used to track line and column
  682.   // numbers.
  683.   while (! token_stack.empty ())
  684.     delete token_stack.pop ();
  685.  
  686.   // Can be reset by defining a function.
  687.   if (! (reading_script_file || reading_fcn_file))
  688.     {
  689.       current_input_column = 1;
  690.       input_line_number = current_command_number - 1;
  691.     }
  692.  
  693.   // Only ask for input from stdin if we are expecting interactive
  694.   // input.
  695.   if ((interactive || really_forced_interactive) &&
  696.       ! (reading_fcn_file || get_input_from_eval_string))
  697.     yyrestart (stdin);
  698.  
  699.   // Clear the buffer for help text.
  700.   help_buf.resize (0);
  701.  
  702.   // Reset other flags.
  703.   lexer_flags.init ();
  704. }
  705.  
  706. // Replace backslash escapes in a string with the real values.
  707.  
  708. static void
  709. do_string_escapes (char *s)
  710. {
  711.   char *p1 = s;
  712.   char *p2 = s;
  713.   while (*p2 != '\0')
  714.     {
  715.       if (*p2 == '\\' && *(p2+1) != '\0')
  716.     {
  717.       switch (*++p2)
  718.         {
  719.         case 'a':
  720.           *p1 = '\a';
  721.           break;
  722.  
  723.         case 'b': // backspace
  724.           *p1 = '\b';
  725.           break;
  726.  
  727.         case 'f': // formfeed
  728.           *p1 = '\f';
  729.           break;
  730.  
  731.         case 'n': // newline
  732.           *p1 = '\n';
  733.           break;
  734.  
  735.         case 'r': // carriage return
  736.           *p1 = '\r';
  737.           break;
  738.  
  739.         case 't': // horizontal tab
  740.           *p1 = '\t';
  741.           break;
  742.  
  743.         case 'v': // vertical tab
  744.           *p1 = '\v';
  745.           break;
  746.  
  747.         case '\\': // backslash
  748.           *p1 = '\\';
  749.           break;
  750.  
  751.         case '\'': // quote
  752.           *p1 = '\'';
  753.           break;
  754.  
  755.         case '"': // double quote
  756.           *p1 = '"';
  757.           break;
  758.  
  759.         default:
  760.           warning ("unrecognized escape sequence `\\%c' --\
  761.  converting to `%c'", *p2, *p2);
  762.           *p1 = *p2;
  763.           break;
  764.         }
  765.     }
  766.       else
  767.     {
  768.       *p1 = *p2;
  769.     }
  770.  
  771.       p1++;
  772.       p2++;
  773.     }
  774.  
  775.   *p1 = '\0';
  776. }
  777.  
  778. // If we read some newlines, we need figure out what column we're
  779. // really looking at.
  780.  
  781. static void
  782. fixup_column_count (char *s)
  783. {
  784.   char c;
  785.   while ((c = *s++) != '\0')
  786.     {
  787.       if (c == '\n' || c == '\r' || c == '')
  788.       current_input_column = 1;
  789.       else
  790.     current_input_column++;
  791.     }
  792. }
  793.  
  794. // Include these so that we don't have to link to libfl.a.
  795.  
  796. #ifdef yywrap
  797. #undef yywrap
  798. #endif
  799. static int
  800. yywrap (void)
  801. {
  802.   return 1;
  803. }
  804.  
  805. // Tell us all what the current buffer is.
  806.  
  807. YY_BUFFER_STATE
  808. current_buffer (void)
  809. {
  810.   return YY_CURRENT_BUFFER;
  811. }
  812.  
  813. // Create a new buffer.
  814.  
  815. YY_BUFFER_STATE
  816. create_buffer (FILE *f)
  817. {
  818.   return yy_create_buffer (f, YY_BUF_SIZE);
  819. }
  820.  
  821. // Start reading a new buffer.
  822.  
  823. void
  824. switch_to_buffer (YY_BUFFER_STATE buf)
  825. {
  826.   yy_switch_to_buffer (buf);
  827. }
  828.  
  829. // Delete a buffer.
  830.  
  831. void
  832. delete_buffer (YY_BUFFER_STATE buf)
  833. {
  834.   yy_delete_buffer (buf);
  835. }
  836.  
  837. // Restore a buffer (for unwind-prot).
  838.  
  839. void
  840. restore_input_buffer (void *buf)
  841. {
  842.   switch_to_buffer ((YY_BUFFER_STATE) buf);
  843. }
  844.  
  845. // Delete a buffer (for unwind-prot).
  846.  
  847. void
  848. delete_input_buffer (void *buf)
  849. {
  850.   delete_buffer ((YY_BUFFER_STATE) buf);
  851. }
  852.  
  853. // Check to see if a character string matches any of the possible line
  854. // styles for plots.
  855.  
  856. static string
  857. plot_style_token (const string& s)
  858. {
  859.   string retval;
  860.  
  861.   static char *plot_styles[] = 
  862.     {
  863.       "boxes",
  864.       "boxerrorbars",
  865.       "boxxyerrorbars",
  866.       "candlesticks",
  867.       "dots",
  868.       "errorbars",
  869.       "financebars",
  870.       "fsteps",
  871.       "histeps",
  872.       "impulses",
  873.       "lines",
  874.       "linespoints",
  875.       "points",
  876.       "steps",
  877.       "vector",
  878.       "xerrorbars",
  879.       "xyerrorbars",
  880.       "yerrorbars",
  881.       0,
  882.     };
  883.  
  884.   char **tmp = plot_styles;
  885.   while (*tmp)
  886.     {
  887.       if (almost_match (*tmp, s.c_str ()))
  888.     {
  889.       retval = *tmp;
  890.       break;
  891.     }
  892.  
  893.       tmp++;
  894.     }
  895.  
  896.   return retval;
  897. }
  898.  
  899. // Check to see if a character string matches any one of the plot
  900. // option keywords.  Don't match abbreviations for clear, since that's
  901. // not a gnuplot keyword (users will probably only expect to be able
  902. // to abbreviate actual gnuplot keywords).
  903.  
  904. static int
  905. is_plot_keyword (const string& s)
  906. {
  907.   const char *t = s.c_str ();
  908.   if (almost_match ("title", t))
  909.     {
  910.       return TITLE;
  911.     }
  912.   else if (almost_match ("using", t))
  913.     {
  914.       lexer_flags.in_plot_using = 1;
  915.       return USING;
  916.     }
  917.   else if (almost_match ("with", t))
  918.     {
  919.       lexer_flags.in_plot_style = 1;
  920.       return WITH;
  921.     }
  922.   else if (strcmp ("clear", t) == 0)
  923.     {
  924.       return CLEAR;
  925.     }
  926.   else
  927.     {
  928.       return 0;
  929.     }
  930. }
  931.  
  932. // Handle keywords.  Could probably be more efficient...
  933.  
  934. static int
  935. is_keyword (const string& s)
  936. {
  937.   if (lexer_flags.plotting && lexer_flags.in_plot_style)
  938.     {
  939.       string sty = plot_style_token (s);
  940.  
  941.       if (! sty.empty ())
  942.     {
  943.       lexer_flags.in_plot_style = 0;
  944.       yylval.tok_val = new token (sty);
  945.       token_stack.push (yylval.tok_val);
  946.       return STYLE;
  947.     }
  948.     }
  949.  
  950.   int l = input_line_number;
  951.   int c = current_input_column;
  952.  
  953.   int len = s.length ();
  954.  
  955.   const octave_kw *kw = octave_kw_lookup (s.c_str (), len);
  956.  
  957.   if (kw)
  958.     {
  959.       yylval.tok_val = 0;
  960.  
  961.       switch (kw->kw_id)
  962.     {
  963.     case all_va_args_kw:
  964.     case break_kw:
  965.     case case_kw:
  966.     case catch_kw:
  967.     case continue_kw:
  968.     case else_kw:
  969.     case elseif_kw:
  970.     case global_kw:
  971.     case otherwise_kw:
  972.     case return_kw:
  973.     case unwind_protect_cleanup_kw:
  974.        break;
  975.  
  976.     case end_kw:
  977.       yylval.tok_val = new token (token::simple_end, l, c);
  978.       break;
  979.  
  980.     case end_try_catch_kw:
  981.       yylval.tok_val = new token (token::try_catch_end, l, c);
  982.       break;
  983.  
  984.     case end_unwind_protect_kw:
  985.       yylval.tok_val = new token (token::unwind_protect_end, l, c);
  986.       break;
  987.  
  988.     case endfor_kw:
  989.       yylval.tok_val = new token (token::for_end, l, c);
  990.       break;
  991.  
  992.     case endfunction_kw:
  993.       yylval.tok_val = new token (token::function_end, l, c);
  994.       break;
  995.  
  996.     case endif_kw:
  997.       yylval.tok_val = new token (token::if_end, l, c);
  998.       break;
  999.  
  1000.     case endswitch_kw:
  1001.       yylval.tok_val = new token (token::switch_end, l, c);
  1002.       break;
  1003.  
  1004.     case endwhile_kw:
  1005.       yylval.tok_val = new token (token::while_end, l, c);
  1006.       break;
  1007.  
  1008.     case for_kw:
  1009.     case while_kw:
  1010.       promptflag--;
  1011.       lexer_flags.looping++;
  1012.       break;
  1013.  
  1014.     case if_kw:
  1015.     case try_kw:
  1016.     case switch_kw:
  1017.     case unwind_protect_kw:
  1018.       promptflag--;
  1019.       break;
  1020.  
  1021.     case gplot_kw:
  1022.       lexer_flags.plotting = 1;
  1023.       yylval.tok_val = new token (token::two_dee, l, c);
  1024.       break;
  1025.  
  1026.     case gsplot_kw:
  1027.       lexer_flags.plotting = 1;
  1028.       yylval.tok_val = new token (token::three_dee, l, c);
  1029.       break;
  1030.  
  1031.     case replot_kw:
  1032.       lexer_flags.plotting = 1;
  1033.       yylval.tok_val = new token (token::replot, l, c);
  1034.       break;
  1035.  
  1036.     case function_kw:
  1037.       if (lexer_flags.defining_func)
  1038.         {
  1039.           error ("function keyword invalid within a function body");
  1040.  
  1041.           if ((reading_fcn_file || reading_script_file)
  1042.           && ! curr_fcn_file_name.empty ())
  1043.         error ("defining new function near line %d of file `%s.m'",
  1044.                input_line_number, curr_fcn_file_name.c_str ());
  1045.           else
  1046.         error ("defining new function near line %d",
  1047.                input_line_number);
  1048.  
  1049.           return LEXICAL_ERROR;
  1050.         }
  1051.       else
  1052.         {
  1053.           tmp_local_sym_tab = new symbol_table ();
  1054.           curr_sym_tab = tmp_local_sym_tab;
  1055.           lexer_flags.defining_func = 1;
  1056.           promptflag--;
  1057.           lexer_flags.beginning_of_function = 1;
  1058.           if (! (reading_fcn_file || reading_script_file))
  1059.         input_line_number = 1;
  1060.         }
  1061.       break;
  1062.  
  1063.     default:
  1064.       panic_impossible ();
  1065.     }
  1066.  
  1067.       if (! yylval.tok_val)
  1068.     yylval.tok_val = new token (l, c);
  1069.  
  1070.       token_stack.push (yylval.tok_val);
  1071.  
  1072.       return kw->tok;
  1073.     }
  1074.  
  1075.   return 0;
  1076. }
  1077.  
  1078. // Try to find an identifier.  All binding to global or builtin
  1079. // variables occurs when expressions are evaluated.
  1080.  
  1081. static symbol_record *
  1082. lookup_identifier (const string& name)
  1083. {
  1084.   return curr_sym_tab->lookup (name, 1, 0);
  1085. }
  1086.  
  1087. static bool
  1088. is_variable (const string& name)
  1089. {
  1090.   symbol_record *sr = curr_sym_tab->lookup (name, 0, 0);
  1091.  
  1092.   return sr && sr->is_variable ();
  1093. }
  1094.  
  1095. static void
  1096. force_local_variable (const string& name)
  1097. {
  1098.   symbol_record *sr = curr_sym_tab->lookup (name, 1, 0);
  1099.  
  1100.   if (sr)
  1101.     sr->define (octave_value ());
  1102. }
  1103.  
  1104. // Grab the help text from an function file.  Always overwrites the
  1105. // current contents of help_buf.
  1106.  
  1107. // XXX FIXME XXX -- gobble_leading_white_space() in variables.cc
  1108. // duplicates some of this code!
  1109.  
  1110. static void
  1111. grab_help_text (void)
  1112. {
  1113.   help_buf.resize (0);
  1114.  
  1115.   bool begin_comment = true;
  1116.   bool in_comment = true;
  1117.   int c = 0, d, ct;
  1118.  
  1119.   while ((c = yyinput ()) != EOF)
  1120.     {
  1121.       if (begin_comment)
  1122.     {
  1123.       if (c == '%' || c == '#')
  1124.         continue;
  1125.       else
  1126.         begin_comment = false;
  1127.     }    
  1128.  
  1129.       if (in_comment)
  1130.     {
  1131.       if (c == '\n' || c == '\r' || c == '')
  1132.         {
  1133.           ct = 0;
  1134.           d  = c;
  1135.  
  1136.           do
  1137.         {
  1138.           if (d == '\n' || d == '')
  1139.             {
  1140.               if (++ct > 1)  break;
  1141.               help_buf += (char) '\n';
  1142.             }
  1143.         }
  1144.           while (((d = yyinput ()) != EOF) &&
  1145.              (d == '\n' || d == '\r' || d == ''));
  1146.  
  1147.           if (d != EOF)  yyunput (d, yytext);
  1148.  
  1149.           in_comment = false;
  1150.         }
  1151.       else
  1152.         help_buf += (char) c;
  1153.     }
  1154.       else
  1155.     {
  1156.       switch (c)
  1157.         {
  1158.         case '%':
  1159.         case '#':
  1160.           in_comment = true;
  1161.           begin_comment = true;
  1162.           break;
  1163.  
  1164.         case ' ':
  1165.         case '\t':
  1166.           break;
  1167.  
  1168.         default:
  1169.           goto done;
  1170.         }
  1171.     }
  1172.     }
  1173.  
  1174.  done:
  1175.  
  1176.   if (c)
  1177.     yyunput (c, yytext);
  1178. }
  1179.  
  1180. // Return 1 if the given character matches any character in the given
  1181. // string.
  1182.  
  1183. static int
  1184. match_any (char c, char *s)
  1185. {
  1186.   char tmp;
  1187.   while ((tmp = *s++) != '\0')
  1188.     {
  1189.       if (c == tmp)
  1190.     return 1;
  1191.     }
  1192.   return 0;
  1193. }
  1194.  
  1195. // Given information about the spacing surrounding an operator,
  1196. // return 1 if it looks like it should be treated as a binary
  1197. // operator.  For example,
  1198. //
  1199. //   [ 1 + 2 ]  or  [ 1+ 2]  or  [ 1+2 ]  ==> binary
  1200.  
  1201. static int
  1202. looks_like_bin_op (int spc_prev, int spc_next)
  1203. {
  1204.   return ((spc_prev && spc_next) || ! spc_prev);
  1205. }
  1206.  
  1207. // Try to determine if the next token should be treated as a postfix
  1208. // unary operator.  This is ugly, but it seems to do the right thing.
  1209.  
  1210. static int
  1211. next_token_is_postfix_unary_op (int spc_prev, char *yytext)
  1212. {
  1213.   int un_op = 0;
  1214.  
  1215.   int c0 = yyinput ();
  1216.   int c1 = yyinput ();
  1217.  
  1218.   yyunput (c1, yytext);
  1219.   yyunput (c0, yytext);
  1220.  
  1221.   int transpose = (c0 == '.' && c1 == '\'');
  1222.   int hermitian = (c0 == '\'');
  1223.  
  1224.   un_op = (transpose || (hermitian && ! spc_prev));
  1225.  
  1226.   return un_op;
  1227. }
  1228.  
  1229. // Try to determine if the next token should be treated as a binary
  1230. // operator.  This is even uglier, but it also seems to do the right
  1231. // thing.  Note that it is only necessary to check the spacing for `+'
  1232. // and `-', since those are the only tokens that can appear as unary
  1233. // ops too.
  1234. //
  1235. // Note that this never returns true for `.', even though it can be a
  1236. // binary operator (the structure reference thing).  The only time
  1237. // this appears to matter is for things like
  1238. //
  1239. //   [ a . b ]
  1240. //
  1241. // which probably doesn't occur that often, can be worked around by
  1242. // eliminating the whitespace, putting the expression in parentheses,
  1243. // or using `whitespace_in_literal_matrix = "ignored"', so I think it
  1244. // is an acceptable change.  It would be quite a bit harder to `fix'
  1245. // this.  (Well, maybe not.  the best fix would be to do away with the
  1246. // specialness of whitespace inside of `[ ... ]').
  1247. //
  1248. // However, we still do check for `.+', `.*', etc.
  1249.  
  1250. static int
  1251. next_token_is_bin_op (int spc_prev, char *yytext)
  1252. {
  1253.   int bin_op = 0;
  1254.  
  1255.   int c0 = yyinput ();
  1256.  
  1257.   switch (c0)
  1258.     {
  1259.     case '+':
  1260.     case '-':
  1261.       {
  1262.     int c1 = yyinput ();
  1263.     yyunput (c1, yytext);
  1264.     int spc_next = (c1 == ' ' || c1 == '\t');
  1265.     bin_op = looks_like_bin_op (spc_prev, spc_next);
  1266.       }
  1267.       break;
  1268.  
  1269.     case '.':
  1270.       {
  1271.     int c1 = yyinput ();
  1272.     yyunput (c1, yytext);
  1273.     bin_op = match_any (c1, "+-*/\\^");
  1274.       }
  1275.       break;
  1276.  
  1277.     case '/':
  1278.     case ':':
  1279.     case '\\':
  1280.     case '^':
  1281.     case '&':
  1282.     case '*':
  1283.     case '|':
  1284.     case '<':
  1285.     case '>':
  1286.     case '~':
  1287.     case '!':
  1288.     case '=':
  1289.       bin_op = 1;
  1290.       break;
  1291.  
  1292.     default:
  1293.       break;
  1294.     }
  1295.  
  1296.   yyunput (c0, yytext);
  1297.  
  1298.   return bin_op;
  1299. }
  1300.  
  1301. // Used to delete trailing white space from tokens.
  1302.  
  1303. static string
  1304. strip_trailing_whitespace (char *s)
  1305. {
  1306.   string retval = s;
  1307.  
  1308.   size_t pos = retval.find_first_of (" \t");
  1309.  
  1310.   if (pos != NPOS)
  1311.     retval.resize (pos);
  1312.  
  1313.   return retval;
  1314. }
  1315.  
  1316. // Discard whitespace, including comments and continuations.
  1317. //
  1318. // Return value is logical OR of the following values:
  1319. //
  1320. //  ATE_NOTHING      : no spaces to eat
  1321. //  ATE_SPACE_OR_TAB : space or tab in input
  1322. //  ATE_NEWLINE      : bare new line in input
  1323.  
  1324. static yum_yum
  1325. eat_whitespace (void)
  1326. {
  1327.   yum_yum retval = ATE_NOTHING;
  1328.   int in_comment = 0;
  1329.   int c;
  1330.   while ((c = yyinput ()) != EOF)
  1331.     {
  1332.       current_input_column++;
  1333.  
  1334.       switch (c)
  1335.     {
  1336.     case ' ':
  1337.     case '\t':
  1338.       retval |= ATE_SPACE_OR_TAB;
  1339.       break;
  1340.  
  1341.     case '':
  1342.     case '\r':
  1343.     case '\n':
  1344.       retval |= ATE_NEWLINE;
  1345.       in_comment = 0;
  1346.       current_input_column = 0;
  1347.       break;
  1348.  
  1349.     case '#':
  1350.     case '%':
  1351.       in_comment = 1;
  1352.       break;
  1353.  
  1354.     case '.':
  1355.       if (in_comment)
  1356.         break;
  1357.       else
  1358.         {
  1359.           if (have_ellipsis_continuation ())
  1360.         break;
  1361.           else
  1362.         goto done;
  1363.         }
  1364.  
  1365.     case '\\':
  1366.       if (in_comment)
  1367.         break;
  1368.       else
  1369.         {
  1370.           if (have_continuation ())
  1371.         break;
  1372.           else
  1373.         goto done;
  1374.         }
  1375.  
  1376.     default:
  1377.       if (in_comment)
  1378.         break;
  1379.       else
  1380.         goto done;
  1381.     }
  1382.     }
  1383.  
  1384.  done:
  1385.   yyunput (c, yytext);
  1386.   current_input_column--;
  1387.   return retval;
  1388. }
  1389.  
  1390. static void
  1391. handle_number (char *yytext)
  1392. {
  1393.   char *tmp = strsave (yytext);
  1394.  
  1395.   char *idx = strpbrk (tmp, "Dd");
  1396.  
  1397.   if (idx)
  1398.     *idx = 'e';
  1399.  
  1400.   double value;
  1401.   int nread = sscanf (tmp, "%lf", &value);
  1402.  
  1403.   delete [] tmp;
  1404.  
  1405.   // If yytext doesn't contain a valid number, we are in deep doo doo.
  1406.  
  1407.   assert (nread == 1);
  1408.  
  1409.   lexer_flags.quote_is_transpose = 1;
  1410.   lexer_flags.cant_be_identifier = 1;
  1411.   lexer_flags.convert_spaces_to_comma = 1;
  1412.  
  1413.   if (lexer_flags.plotting && ! lexer_flags.in_plot_range)
  1414.     lexer_flags.past_plot_range = 1;
  1415.  
  1416.   yylval.tok_val = new token (value, yytext, input_line_number,
  1417.                   current_input_column);
  1418.  
  1419.   token_stack.push (yylval.tok_val);
  1420.  
  1421.   current_input_column += yyleng;
  1422.  
  1423.   do_comma_insert_check ();
  1424. }
  1425.  
  1426. // We have seen a backslash and need to find out if it should be
  1427. // treated as a continuation character.  If so, this eats it, up to
  1428. // and including the new line character.
  1429. //
  1430. // Match whitespace only, followed by a comment character or newline.
  1431. // Once a comment character is found, discard all input until newline.
  1432. // If non-whitespace characters are found before comment
  1433. // characters, return 0.  Otherwise, return 1.
  1434.  
  1435. static int
  1436. have_continuation (int trailing_comments_ok)
  1437. {
  1438.   ostrstream buf;
  1439.  
  1440.   int in_comment = 0;
  1441.   char c;
  1442.   while ((c = yyinput ()) != EOF)
  1443.     {
  1444.       buf << (char) c;
  1445.  
  1446.       switch (c)
  1447.     {
  1448.     case ' ':
  1449.     case '\t':
  1450.       break;
  1451.  
  1452.     case '%':
  1453.     case '#':
  1454.       if (trailing_comments_ok)
  1455.         in_comment = 1;
  1456.       else
  1457.         goto cleanup;
  1458.       break;
  1459.  
  1460.     case '':
  1461.     case '\r':
  1462.     case '\n':
  1463.       current_input_column = 0;
  1464.       promptflag--;
  1465.       return 1;
  1466.  
  1467.     default:
  1468.       if (! in_comment)
  1469.         goto cleanup;
  1470.       break;
  1471.     }
  1472.     }
  1473.  
  1474.   yyunput (c, yytext);
  1475.   return 0;
  1476.  
  1477.  cleanup:
  1478.   buf << ends;
  1479.   char *s = buf.str ();
  1480.   if (s)
  1481.     {
  1482.       int len = strlen (s);
  1483.       while (len--)
  1484.     yyunput (s[len], yytext);
  1485.     }
  1486.   delete [] s;
  1487.   return 0;
  1488. }
  1489.  
  1490. // We have seen a `.' and need to see if it is the start of a
  1491. // continuation.  If so, this eats it, up to and including the new
  1492. // line character.
  1493.  
  1494. static int
  1495. have_ellipsis_continuation (int trailing_comments_ok)
  1496. {
  1497.   char c1 = yyinput ();
  1498.   if (c1 == '.')
  1499.     {
  1500.       char c2 = yyinput ();
  1501.       if (c2 == '.' && have_continuation (trailing_comments_ok))
  1502.     return 1;
  1503.       else
  1504.     {
  1505.       yyunput (c2, yytext);
  1506.       yyunput (c1, yytext);
  1507.     }
  1508.     }
  1509.   else
  1510.     yyunput (c1, yytext);
  1511.  
  1512.   return 0;
  1513. }
  1514.  
  1515. // See if we have a continuation line.  If so, eat it and the leading
  1516. // whitespace on the next line.
  1517. //
  1518. // Return value is the same as described for eat_whitespace().
  1519.  
  1520. static yum_yum
  1521. eat_continuation (void)
  1522. {
  1523.   int retval = ATE_NOTHING;
  1524.   int c = yyinput ();
  1525.   if ((c == '.' && have_ellipsis_continuation ())
  1526.       || (c == '\\' && have_continuation ()))
  1527.     retval = eat_whitespace ();
  1528.   else
  1529.     yyunput (c, yytext);
  1530.  
  1531.   return retval;
  1532. }
  1533.  
  1534. static int
  1535. handle_string (char delim, int text_style)
  1536. {
  1537.   ostrstream buf;
  1538.  
  1539.   int c;
  1540.   int escape_pending = 0;
  1541.  
  1542.   while ((c = yyinput ()) != EOF)
  1543.     {
  1544.       current_input_column++;
  1545.  
  1546.       if (c == '\\')
  1547.     {
  1548.       if (escape_pending)
  1549.         {
  1550.           buf << (char) c;
  1551.           escape_pending = 0;
  1552.         }
  1553.       else
  1554.         {
  1555.           if (have_continuation (0))
  1556.         escape_pending = 0;
  1557.           else
  1558.         {
  1559.           buf << (char) c;
  1560.           escape_pending = 1;
  1561.         }
  1562.         }
  1563.       continue;
  1564.     }
  1565.       else if (c == '.')
  1566.     {
  1567.       if (! have_ellipsis_continuation (0))
  1568.         buf << (char) c;
  1569.     }
  1570.       else if (c == '\n' || c == '\r' || c == '')
  1571.     {
  1572.       error ("unterminated string constant");
  1573.       break;
  1574.     }
  1575.       else if (c == delim)
  1576.     {
  1577.       if (escape_pending)
  1578.         buf << (char) c;
  1579.       else
  1580.         {
  1581.           c = yyinput ();
  1582.           if (c == delim)
  1583.         buf << (char) c;
  1584.           else
  1585.         {
  1586.           yyunput (c, yytext);
  1587.           buf << ends;
  1588.           char *tok = buf.str ();
  1589.           do_string_escapes (tok);
  1590.  
  1591.           if (text_style && lexer_flags.doing_set)
  1592.             {
  1593.               if (tok)
  1594.             {
  1595.               int len = strlen (tok) + 3;
  1596.               char *tmp = tok;
  1597.               tok = new char [len];
  1598.               tok[0] = delim;
  1599.               strcpy (tok+1, tmp);
  1600.               tok[len-2] = delim;
  1601.               tok[len-1] = '\0';
  1602.               delete [] tmp;
  1603.             }
  1604.             }
  1605.           else
  1606.             {
  1607.               lexer_flags.quote_is_transpose = 1;
  1608.               lexer_flags.cant_be_identifier = 1;
  1609.               lexer_flags.convert_spaces_to_comma = 1;
  1610.             }
  1611.  
  1612.           yylval.tok_val = new token (tok);
  1613.           delete [] tok;
  1614.           token_stack.push (yylval.tok_val);
  1615.           return TEXT;
  1616.         }
  1617.         }
  1618.     }
  1619.       else
  1620.     {
  1621.       buf << (char) c;
  1622.     }
  1623.  
  1624.       escape_pending = 0;
  1625.     }
  1626.  
  1627.   return LEXICAL_ERROR;
  1628. }
  1629.  
  1630. static int
  1631. handle_close_brace (int spc_gobbled)
  1632. {
  1633.   if (! nesting_level.none ())
  1634.     {
  1635.       nesting_level.remove ();
  1636.       lexer_flags.braceflag--;
  1637.     }
  1638.  
  1639.   if (lexer_flags.braceflag == 0)
  1640.     BEGIN 0;
  1641.  
  1642.   int c1 = yyinput ();
  1643.   if (c1 == '=')
  1644.     {
  1645.       lexer_flags.quote_is_transpose = 0;
  1646.       lexer_flags.cant_be_identifier = 0;
  1647.       lexer_flags.convert_spaces_to_comma = 1;
  1648.  
  1649.       int c2 = yyinput ();
  1650.       unput (c2);
  1651.       unput (c1);
  1652.  
  1653.       if (c2 != '=' && lexer_flags.maybe_screwed_again)
  1654.     return SCREW_TWO;
  1655.       else
  1656.     return ']';
  1657.     }
  1658.   else
  1659.     {
  1660.       unput (c1);
  1661.  
  1662.       if (lexer_flags.braceflag && Vwhitespace_in_literal_matrix != 2)
  1663.     {
  1664.       int bin_op = next_token_is_bin_op (spc_gobbled, yytext);
  1665.       int postfix_un_op = next_token_is_postfix_unary_op
  1666.         (spc_gobbled, yytext);
  1667.  
  1668.       int other_op = match_any (c1, ",;\n\r]");
  1669.  
  1670.       if (! (postfix_un_op || bin_op || other_op)
  1671.           && nesting_level.is_brace ()
  1672.           && lexer_flags.convert_spaces_to_comma)
  1673.         {
  1674.           unput (',');
  1675.           return ']';
  1676.         }
  1677.     }
  1678.     }
  1679.  
  1680.   lexer_flags.quote_is_transpose = 1;
  1681.   lexer_flags.cant_be_identifier = 0;
  1682.   lexer_flags.convert_spaces_to_comma = 1;
  1683.   return ']';
  1684. }
  1685.  
  1686. static void
  1687. maybe_unput_comma (int spc_gobbled)
  1688. {
  1689.   if (Vwhitespace_in_literal_matrix != 2
  1690.       && nesting_level.is_brace ())
  1691.     {
  1692.       int bin_op = next_token_is_bin_op (spc_gobbled, yytext);
  1693.  
  1694.       int postfix_un_op = next_token_is_postfix_unary_op (spc_gobbled,
  1695.                               yytext);
  1696.  
  1697.       int c1 = yyinput ();
  1698.       int c2 = yyinput ();
  1699.       unput (c2);
  1700.       unput (c1);
  1701.       int sep_op = match_any (c1, ",;\n\r]");
  1702.       int dot_op = (c1 == '.'
  1703.             && (isalpha (c2) || isspace (c2) || c2 == '_'));
  1704.       int index_op = (c1 == '('
  1705.               && (Vwhitespace_in_literal_matrix == 0
  1706.               || ! spc_gobbled));
  1707.  
  1708.       if (! (postfix_un_op || bin_op || sep_op || dot_op || index_op))
  1709.     unput (',');
  1710.     }
  1711. }
  1712.  
  1713. // Figure out exactly what kind of token to return when we have seen
  1714. // an identifier.  Handles keywords.
  1715.  
  1716. static int
  1717. handle_identifier (const string& tok, int spc_gobbled)
  1718. {
  1719.   // It is almost always an error for an identifier to be followed
  1720.   // directly by another identifier.  Special cases are handled
  1721.   // below.
  1722.  
  1723.   lexer_flags.cant_be_identifier = 1;
  1724.  
  1725.   // If we are expecting a structure element, we just want to return
  1726.   // TEXT_ID, which is a string that is also a valid identifier.  But
  1727.   // first, we have to decide whether to insert a comma.
  1728.  
  1729.   if (lexer_flags.looking_at_indirect_ref)
  1730.     {
  1731.       maybe_unput_comma (spc_gobbled);
  1732.  
  1733.       yylval.tok_val = new token (tok, input_line_number,
  1734.                   current_input_column);
  1735.  
  1736.       token_stack.push (yylval.tok_val);
  1737.  
  1738.       lexer_flags.cant_be_identifier = 0;
  1739.       lexer_flags.quote_is_transpose = 1;
  1740.       lexer_flags.convert_spaces_to_comma = 1;
  1741.  
  1742.       current_input_column += yyleng;
  1743.  
  1744.       return TEXT_ID;
  1745.     }
  1746.  
  1747.   // If we have a regular keyword, or a plot STYLE, return it.
  1748.   // Keywords can be followed by identifiers (TOK_RETURN handles
  1749.   // that).
  1750.  
  1751.   int kw_token = is_keyword (tok);
  1752.   if (kw_token)
  1753.     {
  1754.       if (kw_token == STYLE)
  1755.     {
  1756.       current_input_column += yyleng;
  1757.       lexer_flags.quote_is_transpose = 0;
  1758.       lexer_flags.convert_spaces_to_comma = 1;
  1759.       return kw_token;
  1760.     }
  1761.       else
  1762.     TOK_RETURN (kw_token);
  1763.     }
  1764.  
  1765.   // See if we have a plot keyword (title, using, with, or clear).
  1766.  
  1767.   if (lexer_flags.plotting)
  1768.     {
  1769.       // Yes, we really do need both of these plot_range variables.
  1770.       // One is used to mark when we are past all possiblity of a plot
  1771.       // range, the other is used to mark when we are actually between
  1772.       // the square brackets that surround the range.
  1773.  
  1774.       if (! lexer_flags.in_plot_range)
  1775.     lexer_flags.past_plot_range = 1;
  1776.  
  1777.       // Option keywords can't appear in parentheses or braces.
  1778.  
  1779.       int plot_option_kw = 0;
  1780.       if (nesting_level.none ())
  1781.     plot_option_kw = is_plot_keyword (tok);
  1782.  
  1783.       if (lexer_flags.cant_be_identifier && plot_option_kw)
  1784.     TOK_RETURN (plot_option_kw);
  1785.     }
  1786.  
  1787.   int c = yyinput ();
  1788.   yyunput (c, yytext);
  1789.   bool next_tok_is_eq = (c == '=');
  1790.   bool next_tok_is_paren = (c == '(');
  1791.  
  1792.   // Make sure we put the return values of a function in the symbol
  1793.   // table that is local to the function.
  1794.  
  1795.   if (next_tok_is_eq
  1796.       && lexer_flags.defining_func && lexer_flags.maybe_screwed)
  1797.     curr_sym_tab = tmp_local_sym_tab;
  1798.  
  1799.   // Kluge alert.
  1800.   //
  1801.   // If we are looking at a text style function, set up to gobble its
  1802.   // arguments.
  1803.   //
  1804.   // If the following token is `=', or if we are parsing a function
  1805.   // return list or function parameter list, force the symbol to be
  1806.   // inserted as a variable in the current symbol table.
  1807.  
  1808.   if (is_text_function_name (tok) && ! is_variable (tok))
  1809.     {
  1810.       if (next_tok_is_eq
  1811.       || lexer_flags.looking_at_return_list
  1812.       || lexer_flags.looking_at_parameter_list)
  1813.     {
  1814.       force_local_variable (tok);
  1815.     }
  1816.       else if (! next_tok_is_paren)
  1817.     {
  1818.       if (tok == "gset")
  1819.         lexer_flags.doing_set = 1;
  1820.  
  1821.       BEGIN TEXT_FCN;
  1822.     }
  1823.     }
  1824.  
  1825.   // Find the token in the symbol table.
  1826.  
  1827.   yylval.tok_val = new token (lookup_identifier (tok),
  1828.                   input_line_number,
  1829.                   current_input_column);
  1830.  
  1831.   token_stack.push (yylval.tok_val);
  1832.  
  1833.   // After seeing an identifer, it is ok to convert spaces to a comma
  1834.   // (if needed).
  1835.  
  1836.   lexer_flags.convert_spaces_to_comma = 1;
  1837.  
  1838.   // If we are defining a function and we have not seen the parameter
  1839.   // list yet and the next token is `=', return a token that
  1840.   // represents the only return value for the function.  For example,
  1841.   //
  1842.   //   function SCREW = f (args);
  1843.   //
  1844.   // The variable maybe_screwed is reset in parse.y.
  1845.  
  1846.   if (next_tok_is_eq)
  1847.     {
  1848.       current_input_column += yyleng;
  1849.       if (lexer_flags.defining_func && lexer_flags.maybe_screwed)
  1850.     return SCREW;
  1851.       else
  1852.     return NAME;
  1853.     }
  1854.  
  1855.   // At this point, we are only dealing with identifiers that are not
  1856.   // followed by `=' (if the next token is `=', there is no need to
  1857.   // check to see if we should insert a comma (invalid syntax), or
  1858.   // allow a following `'' to be treated as a transpose (the next
  1859.   // token is `=', so it can't be `''.
  1860.  
  1861.   lexer_flags.quote_is_transpose = 1;
  1862.   do_comma_insert_check ();
  1863.  
  1864.   maybe_unput_comma (spc_gobbled);
  1865.  
  1866.   current_input_column += yyleng;
  1867.   return NAME;
  1868. }
  1869.  
  1870. // Print a warning if a function file that defines a function has
  1871. // anything other than comments and whitespace following the END token
  1872. // that matches the FUNCTION statement.
  1873.  
  1874. void
  1875. check_for_garbage_after_fcn_def (void)
  1876. {
  1877.   // By making a newline be the next character to be read, we will
  1878.   // force the parser to return after reading the function.  Calling
  1879.   // yyunput with EOF seems not to work...
  1880.  
  1881.   int in_comment = 0;
  1882.   int lineno = input_line_number;
  1883.   int c;
  1884.   while ((c = yyinput ()) != EOF)
  1885.     {
  1886.       switch (c)
  1887.     {
  1888.     case ' ':
  1889.     case '\t':
  1890.     case ';':
  1891.     case ',':
  1892.       break;
  1893.  
  1894.     case '':
  1895.     case '\r':
  1896.     case '\n':
  1897.       if (in_comment)
  1898.         in_comment = 0;
  1899.       break;
  1900.  
  1901.     case '%':
  1902.     case '#':
  1903.       in_comment = 1;
  1904.       break;
  1905.  
  1906.     default:
  1907.       if (in_comment)
  1908.         break;
  1909.       else
  1910.         {
  1911.           warning ("ignoring trailing garbage after end of function\n\
  1912.          near line %d of file `%s.m'", lineno, curr_fcn_file_name.c_str ());
  1913.           
  1914.           yyunput ('\n', yytext);
  1915.           return;
  1916.         }
  1917.     }
  1918.     }
  1919.   yyunput ('\n', yytext);
  1920. }
  1921.  
  1922. void
  1923. lexical_feedback::init (void)
  1924. {
  1925.   // Not initially defining a function.
  1926.   beginning_of_function = 0;
  1927.   defining_func = 0;
  1928.  
  1929.   // Not parsing a function return or parameter list.
  1930.   looking_at_return_list = 0;
  1931.   looking_at_parameter_list = 0;
  1932.  
  1933.   // Not initially defining a matrix list.
  1934.   braceflag = 0;
  1935.  
  1936.   // Next token can be identifier.
  1937.   cant_be_identifier = 0;
  1938.  
  1939.   // No need to do comma insert or convert spaces to comma at
  1940.   // beginning of input. 
  1941.   convert_spaces_to_comma = 1;
  1942.   do_comma_insert = 0;
  1943.  
  1944.   // Not initially doing any plotting or setting of plot attributes.
  1945.   doing_set = 0;
  1946.   in_plot_range = 0;
  1947.   in_plot_style = 0;
  1948.   in_plot_using = 0;
  1949.   past_plot_range = 0;
  1950.   plotting = 0;
  1951.  
  1952.   // Not initially inside a loop or if statement.
  1953.   looping = 0;
  1954.  
  1955.   // Not initially looking at indirect references.
  1956.   looking_at_indirect_ref = 0;
  1957.  
  1958.   // Not initially screwed by `function [...] = f (...)' syntax.
  1959.   maybe_screwed = 0;
  1960.   maybe_screwed_again = 0;
  1961.  
  1962.   // Quote marks strings intially.
  1963.   quote_is_transpose = 0;
  1964. }
  1965.  
  1966. int
  1967. whitespace_in_literal_matrix (void)
  1968. {
  1969.   int pref = 0;
  1970.   string val = builtin_string_variable ("whitespace_in_literal_matrix");
  1971.   if (! val.empty ())
  1972.     {
  1973.       if (val.compare ("ignore", 0, 6) == 0)
  1974.     pref = 2;
  1975.       else if (val.compare ("traditional", 0, 11) == 0)
  1976.     pref = 1;
  1977.     }
  1978.   Vwhitespace_in_literal_matrix = pref;
  1979.   return 0;
  1980. }
  1981.  
  1982. void
  1983. symbols_of_lex (void)
  1984. {
  1985.   DEFVAR (whitespace_in_literal_matrix, "", 0, whitespace_in_literal_matrix,
  1986.     "control auto-insertion of commas and semicolons in literal matrices");
  1987. }
  1988.  
  1989. // Maybe someday...
  1990. //
  1991. // "+="        return ADD_EQ;
  1992. // "-="        return SUB_EQ;
  1993. // "*="        return MUL_EQ;
  1994. // "/="        return DIV_EQ;
  1995. // "\\="    return LEFTDIV_EQ;
  1996. // ".+="    return ADD_EQ;
  1997. // ".-="    return SUB_EQ;
  1998. // ".*="    return EMUL_EQ;
  1999. // "./="    return EDIV_EQ;
  2000. // ".\\="    return ELEFTDIV_EQ;
  2001.  
  2002. /*
  2003. ;;; Local Variables: ***
  2004. ;;; mode: C++ ***
  2005. ;;; End: ***
  2006. */
  2007.